#include "src/rpc/protobuf_codec.h"

#include <memory>
#include <string>

#include "netlib/base/time_stamp.h"
#include "netlib/net/call_backs.h"
#include "netlib/net/socket/buffer.h"
#include "src/rpc/rpc.pb.h"
#include "gtest/gtest.h"

using namespace netlib;
using namespace netlib::rpc;
using namespace netlib::net;

constexpr MessageType kType = netlib::rpc::kResponse;
constexpr int64_t kId = 23333;
const std::string kService = "test-service";
const std::string kMethod = "test-method";
const std::string kResponseContent = "response of protobuf codec test";

void TestProtobufMessageCallback(const TcpConnectionPtr& conn,
                                 std::unique_ptr<ProtobufMessage>&& msg,
                                 Timestamp ts) {
	msg->PrintDebugString();
	auto rpc_msg = dynamic_cast<RpcMessage*>(msg.get());
	EXPECT_EQ(rpc_msg->type(), kType);
	EXPECT_EQ(rpc_msg->id(), kId);
	EXPECT_EQ(rpc_msg->service(), kService);
	EXPECT_EQ(rpc_msg->method(), kMethod);
	EXPECT_EQ(rpc_msg->response(), kResponseContent);
}

TEST(ProtobufCodecTest, SimpleTest) {
	// RpcMessage msg;
	RpcMessage msg;
	msg.set_type(kType);
	msg.set_id(kId);
	msg.set_service(kService);
	msg.set_method(kMethod);
	msg.set_response(kResponseContent);

	// Expected buffer
	Buffer expected_buffer;
	auto str = msg.SerializeAsString();
	int32_t checksum{};
	for (char ch : str) {
		checksum += ch;
	}
	expected_buffer.Append(str);
	expected_buffer.Append(&checksum, sizeof(checksum));
	int32_t size = str.size() + 4;
	expected_buffer.Prepend(&size, sizeof(size));

	ProtobufCodec<RpcMessage> codec(TestProtobufMessageCallback);
	TcpConnectionPtr conn(nullptr);
	codec.OnMessage(conn, &expected_buffer, Timestamp());
}